<?php
// +----------------------------------------------------------------------
// | INPHP
// | Copyright (c) 2023 https://inphp.cc All rights reserved.
// | Author: 幺月儿(https://gitee.com/lulanyin) Email: inphp@qq.com
// | 该文件的开源协议以所在项目的LICENSE文件为准，请遵守开源协议要求
// +----------------------------------------------------------------------
// | 账户资产
// +----------------------------------------------------------------------
namespace app\finance\model;

use Inphp\Core\Db\PDO\Model;
use Inphp\Core\Middlewares;
use Inphp\Core\Util\Log;

class RefundModel extends Model
{
    /**
     * 主表名
     * @var string
     */
    protected string $tableName = "finance_refund";

    /**
     * 主键
     * @var string
     */
    protected string $primaryKey = "id";

    /**
     * 确认退款
     * @param array $refund
     * @return array|bool
     */
    public static function confirm(array $refund): array|bool
    {
        //状态
        $state = $refund["state"] ?? 0;
        if ($state == 2 && $refund["refund"] == 0) {
            //未退款，可执行
            //资产列表，直接退回资产
            $balanceList = array_keys(getFinanceConfig("balance.list"));
            //其它无需处理的退款，直接不处理
            $otherPayments = getFinanceConfig("cashier.otherPayments");
            $otherPayments = is_array($otherPayments) ? array_keys($otherPayments) : [];
            $onlinePayments = \app\finance\model\CashierModel::onlinePayments();
            $onlinePayments = !empty($onlinePayments) ? array_keys($onlinePayments) : [];

            //统一退款参数
            $params = [
                //退款ID
                "refundId"      => $refund["id"],
                //收银单
                "cashierId"     => $refund["cashierId"],
                //订单支付总金额
                "payedAmount"   => $refund["payedAmount"],
                //本次退款金额
                "amount"        => $refund["amount"],
                //第三方支付不可缺少的参数
                //支付方式
                "payment"       => $refund["payment"],
                //第三方支付的流水ID
                "payedTradeNo"  => $refund["payedTradeNo"],
                //支付使用的APPID
                "appId"         => $refund["paymentAppId"],
                //退款原因
                "reason"        => $refund["bak"],
                //其它数据，异步通知需要
                //订单类型
                "orderType"     => $refund["orderType"],
                //订单号
                "orderId"       => $refund["orderId"]
            ];

            if (in_array($refund["payment"], $balanceList)) {
                //直接返回到余额，完事
                if (!BalanceModel::plus($refund["uid"], $refund["payment"], $refund["amount"], "refund", $refund["bak"], 0, $refund["editor"])) {
                    return false;
                }
                //标记
                $r = RefundModel::emptyQuery()
                    ->where("id", $refund["id"])
                    ->update([
                        //状态标记为1
                        "state"         => 1,
                        //退款标记为1
                        "refund"        => 1,
                        //记录最后退款时间
                        "refundTime"    => date("Y-m-d H:i:s")
                    ]);
                if ($r) {
                    $params["refundAmount"] = $refund["amount"];
                    //更新收银单据
                    @CashierModel::emptyQuery()
                        ->where("id", $refund["cashierId"])
                        ->increment("refundAmount", $refund["amount"])
                        ->setRaw("refundId", "if(`refundId` is null or `refundId`='', '{$refund['id']}', concat(`refundId`, ',{$refund['id']}'))")
                        ->set("refund", 1)
                        ->set("refundTime", date("Y-m-d H:i:s"))
                        ->update();
                    //执行通知
                    self::notify($params);
                    return $params;
                }
                return false;
            } else {
                $refundAmount = $params["amount"];
                $refundResult = null;
                if (in_array($refund["payment"], $onlinePayments)) {
                    //需要第三方处理
                    $result = Middlewares::process(FINANCE_REFUND, $params);
                    if (is_array($result) && !empty($result)) {
                        $res = mergeArray2to1($result);
                        Log::writeToEnd(RUNTIME."/logs/finance/refund/".date("Ymd").".txt", "{$params['cashierId']} res:".json_encode($res));
                        if (empty($res) || $res["error"] != 0) {
                            return false;
                        }
                        //需要在这里判断好正确的退款金额，是否退款处理成功
                        $data = $res["data"] ?? [];
                        $refundAmount = $data["refundAmount"] ?? 0;
                        $refundResult = $data["result"] ?? null;
                    }
                }
                $db = RefundModel::emptyQuery()
                    ->where("id", $refund["id"])
                    ->set([
                        //如果是第三方支付，标记为等待退款
                        "refund"        => !in_array($refund["payment"], $onlinePayments) ? 1 : 2,
                        "refundTime"    => date("Y-m-d H:i:s"),
                        "refundAmount"  => $refundAmount,
                        "refundResult"  => !empty($refundResult) ? (is_array($refundResult) ? json_encode($refundResult, 256) : $refundResult) : ($res['message'] ?? null),
                        "state"         => 1
                    ]);
                if ($db->update()) {
                    //实际退款金额
                    $params["refundAmount"] = $refundAmount;
                    //更新收银单据
                    if ($refundAmount > 0) {
                        @CashierModel::emptyQuery()
                            ->where("id", $refund["cashierId"])
                            ->increment("refundAmount", $refundAmount)
                            ->setRaw("refundId", "if(`refundId` is null or `refundId`='', '{$refund['id']}', concat(`refundId`, ',{$refund['id']}'))")
                            ->set("refund", 1)
                            ->set("refundTime", date("Y-m-d H:i:s"))
                            ->update();
                    }
                    //直接用参数通知
                    if (!in_array($refund["payment"], $onlinePayments)) {
                        //仅在不是在线支付的情况下通知，在线支付的，需要等
                        self::notify($params);
                    }
                    return $params;
                } else {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 第三方支付统一异步通知
     * @param array $params
     * @return bool
     */
    public static function onlineRefundNotify(array $params): bool
    {
        //查询
        $refund = self::emptyQuery("r")
            ->join(CashierModel::as("c"), "r.cashierId=c.id")
            ->where("r.id", $params["refundId"])
            ->where("r.cashierId", $params["cashierId"])
            ->select([
                "r.*",
                "c.orderId, c.orderType, c.payedAmount"
            ])->first();
        if (empty($refund)) {
            return true;
        }
        $refundResult = $params["result"] ?? "";
        //必须是没退过款的
        $db = RefundModel::emptyQuery()
            ->where("id", $refund["id"])
            ->set([
                //如果是第三方支付，标记为等待退款
                "refund"        => 1,
                "refundTime"    => date("Y-m-d H:i:s"),
                "refundAmount"  => $params["refundAmount"],
                "outRefundId"   => $params["outRefundId"],
                "refundResult"  => is_array($refundResult) ? json_encode($refundResult, 256) : $refundResult,
                "state"         => 1
            ]);
        if ($db->update()) {
            //构造通知参数
            self::notify([
                //退款ID
                "refundId"      => $refund["id"],
                //收银单
                "cashierId"     => $refund["cashierId"],
                //订单支付总金额
                "payedAmount"   => $refund["payedAmount"],
                //本次退款金额
                "amount"        => $refund["amount"],
                //实际退款金额
                "refundAmount"  => $params["refundAmount"],
                //第三方支付不可缺少的参数
                //支付方式
                "payment"       => $refund["payment"],
                //退款原因
                "reason"        => $refund["bak"],
                //其它数据，异步通知需要
                //订单类型
                "orderType"     => $refund["orderType"],
                //订单号
                "orderId"       => $refund["orderId"]
            ]);
            return true;
        } else {
            return false;
        }
    }

    /**
     * 退款成功异步通知内部系统
     * @param array $params
     */
    public static function notify(array $params)
    {
        Middlewares::process(FINANCE_REFUND_NOTIFY, $params);
    }
}